package com.bcinfo.iccard.codec;

import java.io.InputStream;
import java.util.Arrays;

import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.log4j.Logger;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;

import com.bcinfo.iccard.msg.ISOMessageFactory;
import com.bcinfo.iccard.msg.Message;
import com.solab.iso8583.IsoMessage;
import com.solab.iso8583.MessageFactory;
/**
 * ISO8583报文解析器
 * 用于ISO8583协议报文的解析、MAC校验
 * @author wangguangchun
 *
 */
public class ISO8583Decoder extends CumulativeProtocolDecoder  {

	private static Logger _logger=Logger.getLogger(ISO8583Decoder.class);
	private MessageFactory<IsoMessage> mfact= ISOMessageFactory.getInstance();
	@Override
	protected boolean doDecode(IoSession session, IoBuffer in,
			ProtocolDecoderOutput out) throws Exception {
		if(_logger.isDebugEnabled()){
			_logger.debug("doDecode: client "+session.getRemoteAddress()+",IoBuffer:"+in.getHexDump());
		}
		Message incoming=new Message();
		InputStream inStream=in.asInputStream();
		incoming.setSize(in.limit());
		//报文长度+tpdu头共计7个字节
        if(in.limit()>7){
        	byte[] lenBuf=new byte[2];
        	//读报文长度
        	inStream.read(lenBuf);
        	int totalSize = CodeUtils.byteToInt(lenBuf);
        	byte[] tpduBuf=new byte[5];
        	//读TPDU头
        	inStream.read(tpduBuf);
        	if(_logger.isDebugEnabled()){
        		_logger.debug("got message buffer size:"+totalSize+",tpdu buffer:"+Arrays.toString(tpduBuf));
        	}
        	byte[] msgBuf=new byte[totalSize-5];
        	//读消息体
        	inStream.read(msgBuf);
        	//解析消息
        	try
            {
        	    IsoMessage isoMsg = mfact.parseMessage(msgBuf, 4);
                if(isoMsg!=null){
                    if(_logger.isDebugEnabled()){
                        _logger.debug("got iso8583 message:\n");
                        ISOMessageFactory.print(isoMsg);
                    }
                    incoming.setMsg(isoMsg);
                    incoming.setTpdu(tpduBuf);
                }
            }
            catch (Exception e)
            {
                _logger.error("bad request message!");
                _logger.error(ExceptionUtils.getStackTrace(e));
            }
        	
        }else{
        	_logger.error("bad request message!");
        }
        inStream.close();
        out.write(incoming);  
        return false;  
    }
}
